package cn.wjh.business.service.impl;

import cn.wjh.business.asyncTask.BusinessAsyncFactory;
import cn.wjh.business.config.TLateConfig;
import cn.wjh.business.config.YouDaoConfig;
import cn.wjh.business.domain.Translate;
import cn.wjh.business.domain.TranslateHistory;
import cn.wjh.business.domain.TranslateResult;
import cn.wjh.business.domain.vo.TranslateVo;
import cn.wjh.business.domain.vo.YouDaoTranslateResultVo;
import cn.wjh.business.mapper.TranslateMapper;
import cn.wjh.business.service.ITranslateHistoryService;
import cn.wjh.business.service.ITranslateService;
import cn.wjh.common.core.redis.RedisCache;
import cn.wjh.common.exception.ServiceException;
import cn.wjh.common.utils.DateUtils;
import cn.wjh.common.utils.SecurityUtils;
import cn.wjh.common.utils.spring.SpringUtils;
import cn.wjh.common.utils.uuid.IdUtils;
import cn.wjh.common.utils.uuid.UUID;
import cn.wjh.framework.manager.AsyncManager;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.wjh.business.asyncTask.BusinessAsyncFactory.getTranslate;

/**
 * 翻译Service业务层处理
 *
 * @author jiraWu
 * @date 2023-11-30
 */
@Service
public class TranslateServiceImpl extends ServiceImpl<TranslateMapper, Translate> implements ITranslateService {
    @Resource
    private TranslateMapper translateMapper;
    @Resource
    private TLateConfig config;

    @Resource
    private ITranslateHistoryService translateHistoryService;

    @Resource
    private YouDaoConfig youDaoConfig;
    @Resource
    private RedisCache redisCache;

    /**
     * 查询翻译
     *
     * @param translateId 翻译主键
     * @return 翻译
     */
    @Override
    public Translate selectTranslateByTranslateId(Long translateId) {
        Translate translate = translateMapper.selectTranslateByTranslateId(translateId);
        translate.setChildren(translateMapper.topVersionChildrenByParent(translate));
        return translate;
    }

    /**
     * 查询翻译列表
     *
     * @param translate 翻译
     * @return 翻译
     */
    @Override
    public List<Translate> selectTranslateList(Translate translate) {
        return translateMapper.selectTranslateList(translate);
    }

    /**
     * 新增翻译
     *
     * @param translate 翻译
     * @return 结果
     */
    @Override
    @Transactional
    public int insertTranslate(Translate translate) {
        translate.setUserId(SecurityUtils.getUserId());
        translate.setCreateTime(DateUtils.getNowDate());
        translate.setCreateBy(SecurityUtils.getUsername());
        translate.setStringKey(IdUtils.fastUUID());
        int row = translateMapper.insertTranslate(translate);
        //插入子集
        insertTranslateChild(translate);
        return row;
    }

    /**
     * 插入子集
     */
    @Transactional
    public void insertTranslateChild(Translate translate) {
        List<Translate> children = translate.getChildren();
        if (null == children || children.isEmpty())
            return;
        Long parentId = translate.getTranslateId();//父级Id
        children.forEach(item -> {
            item.setParentId(parentId);
            item.setProductId(translate.getProductId());
            item.setUserId(translate.getUserId());
            item.setCreateBy(translate.getCreateBy());
            item.setCreateTime(translate.getCreateTime());
            item.setStringKey(translate.getStringKey());
        });
        this.saveBatch(children);
    }


    /**
     * 修改翻译
     *
     * @param translate 翻译
     * @return 结果
     */
    @Override
    @Transactional
    public int updateTranslate(Translate translate) {
        translate.setUserId(SecurityUtils.getUserId());
        translate.setUpdateTime(DateUtils.getNowDate());
        translate.setUpdateBy(SecurityUtils.getUsername());
//        删除
        deleteTranslateChild(translate);
//        插入
        insertTranslateChild(translate);
        return translateMapper.updateTranslate(translate);
    }

    /**
     * 删除子集
     */
    @Transactional
    public void deleteTranslateChild(Translate translate) {
        LambdaQueryWrapper<Translate> queryWrapper = new QueryWrapper<Translate>().lambda()
                .eq(Translate::getParentId, translate.getTranslateId());
        this.remove(queryWrapper);
    }

    /**
     * 批量删除翻译
     *
     * @param translateIds 需要删除的翻译主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteTranslateByTranslateIds(List<Long> translateIds) {
        translateIds.forEach(translateId -> {
            Translate t = this.getById(translateId);
            /*将翻译历史的保存状态也同步更新一下*/
            if (null != t && null != t.getTranslateHistoryId()) {
                LambdaUpdateWrapper<TranslateHistory> updateWrapper = new UpdateWrapper<TranslateHistory>().lambda()
                        .set(TranslateHistory::getSaveFlag, false)
                        .eq(TranslateHistory::getTranslateHistoryId, t.getTranslateHistoryId());
                translateHistoryService.update(updateWrapper);
            }
            Translate translate = new Translate();
            translate.setTranslateId(translateId);
            this.deleteTranslateChild(translate);
        });
        return translateMapper.deleteBatchIds(translateIds);
    }


    /**
     * 翻译
     */
    public Map<String, String> translate(TranslateVo translate) {
        List<TranslateResult> translateResultList = translateMapper.translate(translate);
        Map<String, String> result = new LinkedHashMap<>();
        Set<String> toList = translate.getToList();
        toList.forEach(to -> result.put(to, ""));//先生成一个结果
        translateResultList.forEach(trl -> result.put(trl.getKey(), trl.getValue()));//覆盖之前的结果
        saveTranslationHistory(translate, result);//保存翻译历史
        return result;
    }

    /**
     * 保存翻译历史
     */
    private void saveTranslationHistory(TranslateVo translate, Map<String, String> result) {
        boolean flag = translateHistoryService.uniqueTranslationHistory(translate);//是否存在
        if (!flag)
            return;
        //翻译历史服务
        TranslateHistory history = new TranslateHistory();
        history.setCreateTime(DateUtils.getNowDate());
        history.setUserId(SecurityUtils.getUserId());
        history.setProductId(translate.getProductId());
        history.setQ(translate.getQ());
        history.setFromLanguageCode(translate.getFrom());
        history.setToLanguageCode(String.join(",", translate.getToList()));
        history.setResult(JSON.toJSONString(result));
        translateHistoryService.insertTranslateHistory(history);
    }


    /**
     * 有道翻译api翻译
     */
    @Override
    public Map<String, String> translateYouDao(TranslateVo translate) {
        Set<String> toList = translate.getToList();//目标语言列表
        List<YouDaoTranslateResultVo> list = toList.stream().map(to -> {
            try {
                return getYouDaoTranslateResult(translate, to);
            } catch (NoSuchAlgorithmException | JsonProcessingException e) {
                throw new ServiceException(e.getMessage());
            }
        }).collect(Collectors.toList());
        Map<String, String> result = new LinkedHashMap<>();
        toList.forEach(to -> result.put(to, ""));//先生成一个结果
        list.forEach(item -> {
            List<String> translation = item.getTranslation();
            String value = translation != null && !translation.isEmpty() ? translation.get(0).toLowerCase() : "";
            result.put(item.getLanguageCode(), value);
        });
        saveTranslationHistory(translate, result);//保存翻译历史
        return result;
    }


    /**
     * 获取有道翻译API返回的结果
     * 1.查询本地的数据库数据
     * 1.1 存在 直接返回
     * 1.2 不存在 调用有道翻译的api获取结果返回
     * 1.2.1 开启异步线程 查询所有语言的翻译 保存至本地数据库
     */
    @Override
    public YouDaoTranslateResultVo getYouDaoTranslateResult(TranslateVo translate, String to) throws JsonProcessingException, NoSuchAlgorithmException {
        String q = translate.getQ();//待翻译的文本
        String from = translate.getFrom();//源语言
        String value = translateMapper.translateByOne(translate.getProductId(), q, from, to);//看看系统中是否拥有属于该词条的翻译 如果有直接返回 没有就调用翻译api
        if (null != value && !value.isEmpty()) {
            // 如果本地数据库有 则直接返回翻译结果
            return new YouDaoTranslateResultVo(to, Collections.singletonList(value), q);
        }
        TranslateHistory translateHistory = translateHistoryService.getTranslationHistoryByTranslate(null, translate);//看看是否有历史翻译记录
        if (null != translateHistory) {
            //如果有翻译历史 处理翻译历史结果
            String result = translateHistory.getResult();
            Map<String, String> resultMap = (Map<String, String>) JSON.parse(result);//{languageCode,value}
            value = resultMap.get(to);//把这个语言的结果取出来
        }
        // 判断这个值是否为空 为空时请求有道翻译api获取结果，否则直接返回
        if (null == value || value.isEmpty()) {
            try {
                return youDaoConfig.sendRequest(q, from, to);
            } catch (JsonProcessingException | NoSuchAlgorithmException e) {
                throw new ServiceException("翻译失败,请重试！", 400);
            }
        } else {
            return new YouDaoTranslateResultVo(to, Collections.singletonList(value), q);
        }

    }

    /**
     * 保存翻译版本
     */
    @Override
    @Transactional
    public boolean saveTranslationVersion(Translate translate) {
        /*为了翻译版本不重复 */
        TranslateHistory translateHistory = translateHistoryService.getTranslationHistoryByTranslate(SecurityUtils.getUserId(), translate);
        TranslateHistory history = new TranslateHistory();
        history.setSaveFlag(true);
        if (null != translateHistory && translateHistory.getSaveFlag()) {
            // 存在的
            history.setTranslateHistoryId(translateHistory.getTranslateHistoryId());
            return translateHistoryService.updateById(history);
        }
        this.insertTranslate(translate);//保存版本
        history.setTranslateHistoryId(translate.getTranslateHistoryId());
        return translateHistoryService.updateById(history);
    }


    /**
     * 获取顶级翻译版本列表
     */
    @Override
    public List<Translate> topVersionList(Translate translate) {
        List<Translate> translateList = translateMapper.topVersionList(translate);
        /*获取子集*/
        translateList.forEach(item -> {
            List<Translate> list = translateMapper.topVersionChildrenByParent(item);
            item.setChildren(null == list ? new ArrayList<>() : list);
        });
        return translateList;
    }


    /**
     * 获取一个有道翻译结果
     */
    @Override
    public String translateYouDaoOneResult(TranslateVo translate) {
        try {
            YouDaoTranslateResultVo youDaoTranslateResult = this.getYouDaoTranslateResult(translate, translate.getTo());
            List<String> list = youDaoTranslateResult.getTranslation();
            return null != list && !list.isEmpty() ? list.get(0) : "";

        } catch (JsonProcessingException | NoSuchAlgorithmException e) {
            throw new ServiceException("翻译失败！请重试！");
        }
    }
}
